package com.ruoyi.quartz.task;

import com.google.common.util.concurrent.*;
import com.ruoyi.bizsys.domain.ExtMonnifyOrder;
import com.ruoyi.bizsys.service.IRepaymentOrderService;
import com.ruoyi.business.service.IBExtMonnifyOrderService;
import com.ruoyi.business.service.IBRepaymentService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.quartz.thread.TransactionTaskThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component("transactionTask")
public class TransactionTask {

    @Autowired
    RedisCache redisCache;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    IBRepaymentService iBRepaymentService;

    @Autowired
    IBExtMonnifyOrderService iBExtMonnifyOrderService;

    @Autowired
    IRepaymentOrderService iRepaymentOrderService;


    public void killAllTransactionThread(){
        log.info("执行杀死全部transaction线程");
        redisTemplate.delete(redisTemplate.keys(BizConstants.TRANSACTION_THREAD+"*"));
    }

    public void runTransaction(){

        List<ExtMonnifyOrder> list = iBExtMonnifyOrderService.getCanRunData();
        int count = list.size();
        if (count > 0) {
            String redisName = BizConstants.TRANSACTION_TASK_DATA;

            int threadStep = 10;//每个线程执行的客户数
            //需要multiple个线程来执行
            int threadCount = count / threadStep;
            if (threadCount * threadStep != count) {
                threadCount++;
            }
            //线程计数器
            final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
            //线程池大小
            int poolSize = 2;

            ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
            ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);

            int threadAccountCount = 0;
            while (threadAccountCount != count) {
                //分页取数startNum
                int startLimit = threadAccountCount;

                threadAccountCount += threadStep;

                if(threadAccountCount>count){
                    threadAccountCount = count;
                }

                String redisName1 = redisName+":"+startLimit+"-"+threadAccountCount;
                List<ExtMonnifyOrder> accountList1 = list.subList(startLimit,threadAccountCount);
                redisCache.setCacheList(redisName1,accountList1);
                redisCache.expire(redisName1,23, TimeUnit.HOURS);

                TransactionTaskThread thread = new TransactionTaskThread("[TransactionTask-"+startLimit+"]", redisName1,
                        iBRepaymentService,redisCache,iRepaymentOrderService);
                ListenableFuture listenableFuture = listeningExecutorService.submit(thread);

                Futures.addCallback(listenableFuture, new FutureCallback<String>() {
                    @Override
                    public void onSuccess(String result) {
                        countDownLatch.countDown();
                        log.info("["+this.getClass().getName()+"]线程处理结果："+ result);
                    }

                    @Override
                    public void onFailure(Throwable throwable) {
                        countDownLatch.countDown();
                        log.info("["+this.getClass().getName()+"]线程处理出错："+ throwable);
                    }
                });
            }

            try {
                countDownLatch.await(3*60, TimeUnit.MINUTES);//超过3个小时放弃
            } catch (InterruptedException e) {
                log.error("transaction当日跑批执行失败，非正常结束", e);
            }
        }else {
            log.info("transaction每日跑批任务没有记录需要执行");
        }

        log.info("transaction每日跑批任务 End>>>>>>>>>>");
        }


    }
